/**
 * 两个链表的第一个公共结点
 *
 * 描述
 * 输入两个无环的单向链表，找出它们的第一个公共结点，如果没有公共节点则返回空。
 * （注意因为传入数据是链表，所以错误测试数据的提示是用其他方式显示的，保证传入数据是正确的）
 *
 * 数据范围：
 * n≤1000
 *
 * 要求：
 * 空间复杂度 O(1)，
 * 时间复杂度 O(n)
 *
 * 例如，输入{1,2,3},{4,5},{6,7}时，两个无环的单向链表的结构如下图所示：
 * 可以看到它们的第一个公共结点的结点值为6，所以返回结点值为6的结点。
 *
 * 输入描述：
 * 输入分为是3段，第一段是第一个链表的非公共部分，第二段是第二个链表的非公共部分，第三段是第一个链表和第二个链表的公共部分。 后台会将这3个参数组装为两个链表，并将这两个链表对应的头节点传入到函数FindFirstCommonNode里面，用户得到的输入只有pHead1和pHead2。
 *
 * 返回值描述：
 * 返回传入的pHead1和pHead2的第一个公共结点，后台会打印以该节点为头节点的链表。
 */

/**
 * 这里我们将两个链表的长度求出来, 然后让长的链表先走多出来的节点数,
 * 后面在一起向后面走, 这样就会同时到达公共节点了
 * 时间复杂度 : O(1)
 * 空间复杂度 : O(n)
 */

public class Main {
    public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {

        // 链表长度
        int n1 = 0, n2 = 0;

        // 打工节点
        ListNode cur1 = pHead1, cur2 = pHead2;

        while (cur1 != null) {
            cur1 = cur1.next;
            n1++;
        }

        while (cur2 != null) {
            cur2 = cur2.next;
            n2++;
        }

        // 多出的长度
        int n = 0;

        // 这里要判断谁更长, 然后赋给 cur1
        if (n1 >= n2) {
            n = n1 - n2;
            cur1 = pHead1;
            cur2 = pHead2;
        } else {
            n = n2 - n1;
            cur1 = pHead2;
            cur2 = pHead1;
        }

        // 长度先走
        while (n != 0) {
            cur1 = cur1.next;
            n--;
        }

        // 遇到相同的几点就停止, 要是没有 cur1 也走到 null 了
        while (cur1 != null) {
            if (cur1.val == cur2.val) {
                break;
            }
            cur1 = cur1.next;
            cur2 = cur2.next;
        }

        // 直接返回 cur1 就可以了
        return cur1;
    }
}

class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}